﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Folder Browse Button Class
 *      A button control for invoking the Folder Brwose dialog.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Text;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Timers;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    ///  A button control for invoking the Folder Brwose dialog.
    /// </summary>
    public partial class FolderBrowseButton : Button
    {
        /*--------------------------------------------------------------------------------------
         * Public Events
         *------------------------------------------------------------------------------------*/
        #region Public Events
        /// <summary>
        /// Occurs just before the common dialog is displayed.
        /// </summary>
        public event EventHandler BeforeDialogDisplay;
        /// <summary>
        /// Occurs when the user cancels the operation.
        /// </summary>
        public event EventHandler UserCancelled;
        /// <summary>
        /// Occurs when the user presses OK on the common dialog.
        /// </summary>
        public event EventHandler OperationSuccess;
        #endregion

        /*--------------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Last result of common dialog operation.
        /// </summary>
        private DialogResult _lastDialogResult = DialogResult.Cancel;
        /// <summary>
        /// Auto size flag.
        /// </summary>
        private bool _autoSize;
        /// <summary>
        /// Show new folder button flag.
        /// </summary>
        private bool _showNewFolderButton;
        /// <summary>
        /// Root folder location.
        /// </summary>
        private Environment.SpecialFolder _rootFolder = Environment.SpecialFolder.Desktop;
        /// <summary>
        /// Description text.
        /// </summary>
        private string _description = string.Empty;
        /// <summary>
        /// Selected path string.
        /// </summary>
        private string _selectedPath = string.Empty;
        #endregion

        /*--------------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public FolderBrowseButton()
            : base()
        {
            InitializeComponent();
        }
        #endregion

        /*--------------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets a value indicating whether the button is to be automatically sized.
        /// </summary>
        /// <value>
        /// <b>true</b> to automatically size the control; otherwise, <b>false</b>.
        /// </value>
        [Browsable(true), Category("Appearance"), Description("Allows automatic sizing based on text content."), DefaultValue(false)]
        public override bool AutoSize
        {
            get { return _autoSize; }
            set
            {
                _autoSize = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets the last result of common dialog operation.
        /// </summary>
        /// <value>
        ///  A <see cref="DialogResult"/> enumerated value indicating the last action.
        /// </value>
        [Browsable(false)]
        public DialogResult LastDialogResult
        {
            get
            {
                return _lastDialogResult;
            }
        }
        /// <summary>
        /// Gets or sets a a value indicating the root folder at which to start the path tree.
        /// </summary>
        /// <value>
        /// A <see cref="Environment.SpecialFolder"/> enumerated value.
        /// </value>
        [Browsable(true), DefaultValue(0), Description("The root folder for the tree view.")]
        public Environment.SpecialFolder RootPath
        {
            get
            {
                return _rootFolder;
            }
            set
            {
                _rootFolder = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the text that appears in the instructions section of a folder browse dialog.
        /// </summary>
        /// <value>
        /// A String that is the text that appears in the instructions section of a file dialog. The default is Empty.
        /// </value>
        [Browsable(true), DefaultValue(""), Description("The instructions text to display on the dialog.")]
        public string Description
        {
            get
            {
                return _description;
            }
            set
            {
                _description = value;
            }
        }
        /// <summary>
        /// Gets or sets a string containing the full path of the file selected in a file dialog.
        /// </summary>
        /// <value>
        /// A String that is the full path of the file selected in the file dialog. The default is Empty.
        /// </value>
        [Browsable(true), DefaultValue(""), Description("Selected path name value.")]
        public string SelectedPath
        {
            get
            {
                return _selectedPath;
            }
            set
            {
                _selectedPath = value;
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether to display the New Folder button on the dialog.
        /// </summary>
        /// <value>
        /// <b>true</b> to show the new folder button; otherwise, <b>false</b>.
        /// </value>
        [Browsable(true), DefaultValue(false), Description("Show or hide the New Folder button on the dialog."),
         Category("Behavior")]
        public bool ShowNewFolderButton
        {
            get
            {
                return _showNewFolderButton;
            }
            set
            {
                _showNewFolderButton = value;
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------------
         * Protected Method Overrides
         *------------------------------------------------------------------------------------*/
        #region Protected Method Overrides
        /// <summary>
        /// Raises the <see cref="E:Click"/> event and displays the specified dialog.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected override void OnClick(EventArgs e)
        {
            //Call base event.
            base.OnClick(e);

            OnBeforeDialogDisplay(EventArgs.Empty);
            ShowFolderDialog();
        }
        #endregion

        /*--------------------------------------------------------------------------------------
         * Protected Event Methods
         *------------------------------------------------------------------------------------*/
        #region Protected Event Methods
        /// <summary>
        /// Paints the control.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            SizeF textSize;

            //Re-set width based on text size.
            if (_autoSize)
            {
                textSize = e.Graphics.MeasureString(Text, Font);
                Width = Convert.ToInt32(textSize.Width) + 15;
            }

            base.OnPaint(e);
        }
        /// <summary>
        /// Raises the <see cref="BeforeDialogDisplay"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnBeforeDialogDisplay(EventArgs e)
        {
            if (BeforeDialogDisplay != null)
                BeforeDialogDisplay(this, e);
        }
        /// <summary>
        /// Raises the <see cref="UserCancelled"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnUserCancelled(EventArgs e)
        {
            if (UserCancelled != null)
                UserCancelled(this, e);
        }
        /// <summary>
        /// Raises the <see cref="OperationSuccess"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected virtual void OnOperationSuccess(EventArgs e)
        {
            if (OperationSuccess != null)
                OperationSuccess(this, e);
        }
        #endregion

        /*--------------------------------------------------------------------------------------
         * Private Methods / Functions
         *------------------------------------------------------------------------------------*/
        #region Private Methods / Functions
        /// <summary>
        /// Displays the Browse-for-folder dialog.
        /// </summary>
        private void ShowFolderDialog()
        {
            FolderBrowserDialog dialog = null;                  //Dialog to be displayed.
            DialogResult result = DialogResult.Cancel;          //Result of dialog interaction.

            //Create and configure the dialog.
            dialog = new FolderBrowserDialog();
            dialog.Description = _description;
            dialog.RootFolder = _rootFolder;
            dialog.SelectedPath = _selectedPath;
            dialog.ShowNewFolderButton = _showNewFolderButton;

            result = dialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                _selectedPath = dialog.SelectedPath;
                OnOperationSuccess(EventArgs.Empty);
            }
            else
            {
                OnUserCancelled(EventArgs.Empty);
            }
            dialog.Dispose();
            dialog = null;
        }
        #endregion
    }
}
